package com.cn.lp.jpa.cq.expression;

import com.cn.lp.jpa.cq.domain.CQField;
import com.cn.lp.jpa.cq.function.Func0;

import java.util.Collection;

/**
 * @author wqr
 * Created by on 2019/8/7
 */
public interface CQCondition<TFrom> {

    CQCondition<TFrom> beginBlock();

    CQCondition<TFrom> not();

    /**
     * 等于
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T> CQLogical<TFrom> eq(CQField field, T v);

    /**
     * 等于
     *
     * @param field1
     * @param field2
     * @return
     */
    CQLogical<TFrom> eq(CQField field1, CQField field2);

    /**
     * 不等于
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T> CQLogical<TFrom> ne(CQField field, T v);

    /**
     * 不等于
     *
     * @param field1
     * @param field2
     * @return
     */
    CQLogical<TFrom> ne(CQField field1, CQField field2);

    /**
     * 大于
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> gt(CQField field, T v);

    /**
     * 大于
     *
     * @param field1
     * @param field2
     * @return
     */
    CQLogical<TFrom> gt(CQField field1, CQField field2);

    /**
     * 大于等于
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> ge(CQField field, T v);

    /**
     * 大于等于
     *
     * @param field1
     * @param field2
     * @param
     * @return
     */
    CQLogical<TFrom> ge(CQField field1, CQField field2);

    /**
     * 小于
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> lt(CQField field, T v);

    /**
     * 小于
     *
     * @param field1
     * @param field2
     * @return
     */
    CQLogical<TFrom> lt(CQField field1, CQField field2);

    /**
     * 小于等于
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> le(CQField field, T v);

    /**
     * 小于等于
     *
     * @param field1
     * @param field2
     * @return
     */
    CQLogical<TFrom> le(CQField field1, CQField field2);

    /**
     * 值在给定值列表中
     *
     * @param field
     * @param values
     * @return
     */
    CQLogical<TFrom> in(CQField field, Collection<?> values);

    /**
     * 值在给定范围中
     *
     * @param field
     * @param v1
     * @param v2
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> between(CQField field, T v1, T v2);

    /**
     * 文本模糊匹配
     *
     * @param field
     * @param v
     * @return
     */
    CQLogical<TFrom> like(CQField field, String v);

    /**
     * 为空
     *
     * @param field
     * @return
     */
    CQLogical<TFrom> isNull(CQField field);

    /**
     * 不为空
     *
     * @param field
     * @return
     */
    CQLogical<TFrom> isNotNull(CQField field);

    // ============================================================================

    /**
     * 等于，当传入的值有效
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T> CQLogical<TFrom> eqOpt(CQField field, T v);


    /**
     * 不等于，当传入的值有效
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T> CQLogical<TFrom> neOpt(CQField field, T v);

    /**
     * 大于，当传入的值有效
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> gtOpt(CQField field, T v);

    /**
     * 大于等于，当传入的值有效
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> geOpt(CQField field, T v);

    /**
     * 小于，当传入的值有效
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> ltOpt(CQField field, T v);

    /**
     * 小于等于，当传入的值有效
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> leOpt(CQField field, T v);

    /**
     * 值在给定值列表中，当传入的值有效
     *
     * @param field
     * @param values
     * @return
     */
    CQLogical<TFrom> inOpt(CQField field, Collection<?> values);

    /**
     * 值在给定范围中，当传入的值有效
     *
     * @param field
     * @param v1
     * @param v2
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> betweenOpt(CQField field, T v1, T v2);

    /**
     * 文本模糊匹配，当传入的值有效
     *
     * @param field
     * @param v
     * @return
     */
    CQLogical<TFrom> likeOpt(CQField field, String v);

    /**
     * 文本模糊匹配，当传入的值有效, 有效时加上%
     * @param field
     * @param v
     * @return
     */
    CQLogical<TFrom> vagueLike(CQField field, String v);

    // ==============================================================================

    /**
     * 等于，当judge函数为true时执行
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T> CQLogical<TFrom> eqIf(Func0<Boolean> judge, CQField field, T v);

//    default CQWhere<TFrom> eqIf(Func0<Boolean> judge, CQField field, IdentifiableEnum identifiableEnum) {
//        if (!judge.call()) {
//            return this;
//        }
//        return eq(field, identifiableEnum);
//    }

    /**
     * 不等于，当judge函数为true时执行
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T> CQLogical<TFrom> neIf(Func0<Boolean> judge, CQField field, T v);

    /**
     * 大于，当judge函数为true时执行
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> gtIf(Func0<Boolean> judge, CQField field, T v);

    /**
     * 大于等于，当judge函数为true时执行
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> geIf(Func0<Boolean> judge, CQField field, T v);

    /**
     * 小于，当judge函数为true时执行
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> ltIf(Func0<Boolean> judge, CQField field, T v);

    /**
     * 小于等于，当judge函数为true时执行
     *
     * @param field
     * @param v
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> leIf(Func0<Boolean> judge, CQField field, T v);

    /**
     * 值在给定值列表中，当judge函数为true时执行
     *
     * @param field
     * @param values
     * @return
     */
    CQLogical<TFrom> inIf(Func0<Boolean> judge, CQField field, Collection<?> values);

    /**
     * 值在给定范围中，当judge函数为true时执行
     *
     * @param field
     * @param v1
     * @param v2
     * @param <T>
     * @return
     */
    <T extends Comparable<T>> CQLogical<TFrom> betweenIf(Func0<Boolean> judge, CQField field, T v1, T v2);

    /**
     * 文本模糊匹配，当judge函数为true时执行
     *
     * @param field
     * @param v
     * @return
     */
    CQLogical<TFrom> likeIf(Func0<Boolean> judge, CQField field, String v);

}
